/*
 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package test3d;

import javafx.application.ConditionalFeature;
import javafx.application.Platform;
import javafx.scene.AmbientLight;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.TriangleMesh;
import javafx.stage.Stage;
import org.junit.Test;
import testharness.VisualTestBase;

/**
 * Basic TriangleMesh validation tests.
 */
public class TriangleMeshValidationTest extends VisualTestBase {

    private Stage testStage;
    private Scene testScene;
    private MeshView meshView;
    private TriangleMesh triMesh;
    private PhongMaterial material;
    private Group root;

    private static final double TOLERANCE = 0.07;
    private static final int WIDTH = 800;
    private static final int HEIGHT = 800;
    private Color bgColor = Color.rgb(10, 10, 40);

    @Test(timeout=5000)
    public void testEmptyMesh() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), WIDTH, HEIGHT, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            triMesh = new TriangleMesh();
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // No warning. Rendering nothing.
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(bgColor, color, TOLERANCE);
        });
    }

    @Test(timeout=5000)
    public void testInvalidPointsLength() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), 800, 800, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            buildBox();
            // set invalid points
            triMesh.getPoints().setAll(1, 1, 1,
                            1, 1, -1,
                            1, -1, 1,
                            1, -1, -1,
                            -1, 1, 1,
                            -1, 1, -1,
                            -1, //-1, 1,
                            -1, -1, -1);
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Rendering nothing. Should receive warning from validatePoints
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(bgColor, color, TOLERANCE);
        });
    }

    @Test(timeout=5000)
    public void testInvalidTexCoordLength() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), 800, 800, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            buildBox();
            // set invalid texcoords
            triMesh.getTexCoords().setAll(0, 0,
                    0, 1,
                    1, //0,
                    1, 1);
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Rendering nothing. Should receive warning from validateTexcoords
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(bgColor, color, TOLERANCE);
        });
    }

    @Test(timeout=5000)
    public void testInvalidFacesLength() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), 800, 800, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            buildBox();
            // set invalid faces
            triMesh.getFaces().setAll(0, 0, 2, 2, 1, 1,
                            2, 2, 3, 3, 1, 1,
                            4, 0, 5, 1, 6, 2,
                            6, 2, 5, 1, 7, 3,
                            0, 0, 1, 1, 4, 2,
                            4, 2, 1, 1, 5, //3,
                            2, 0, 6, 2, 3, 1,
                            3, 1, 6, 2, 7, 3,
                            0, 0, 4, 1, 2, 2,
                            2, 2, 4, 1, 6, 3,
                            1, 0, 3, 1, 5, 2,
                            5, 2, 3, 1, 7, 3);
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Rendering nothing. Should receive warning from validateFaces
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(bgColor, color, TOLERANCE);
        });
    }

    @Test(timeout=5000)
    public void testInvalidFacesIndex() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), 800, 800, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            buildBox();
            triMesh.getFaces().setAll(0, 0, 2, 2, 1, 1,
                            2, 2, 3, 3, 1, 1,
                            4, 0, 5, 1, 6, 2,
                            6, 2, 5, 1, 7, 3,
                            0, 0, 1, 1, 4, 2,
                            4, 2, 1, 1, 5, 8, // 8 is out of bound
                            2, 0, 6, 2, 3, 1,
                            3, 1, 6, 2, 7, 3,
                            0, 0, 4, 1, 2, 2,
                            2, 2, 4, 1, 6, 3,
                            1, 0, 3, 1, 5, 2,
                            5, 2, 3, 1, 7, 3);
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Rendering nothing. Should receive warning from validateFaces
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(bgColor, color, TOLERANCE);
        });
    }

    @Test(timeout=5000)
    public void testInvalidFaceSmoothingGroupsLength() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), 800, 800, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            buildBox();
            // set invalid faceSmoothingGroups
            triMesh.getFaceSmoothingGroups().setAll(1, 1, 1, 1, 2, 2,/* 2, 2,*/ 4, 4, 4, 4);
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Rendering nothing. Should receive warning from validateFacesSmoothingGroups
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(bgColor, color, TOLERANCE);
        });
    }

    @Test(timeout=5000)
    public void testPointsLengthChange() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), 800, 800, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            buildBox();
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(Color.RED, color, TOLERANCE);

            // Valid change of points
            triMesh.getPoints().setAll(1, 1, 1);
        });
        waitFirstFrame();
        runAndWait(() -> {
            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Rendering nothing because faces is invalid.
            // Should receive warning from validateFaces
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(bgColor, color, TOLERANCE);
        });
    }

    @Test(timeout=5000)
    public void testTexCoordsLengthChange() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), 800, 800, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            buildBox();
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(Color.RED, color, TOLERANCE);

            // Valid change of texcoords
            triMesh.getTexCoords().setAll(0, 0, 1, 1);
        });
        waitFirstFrame();
        runAndWait(() -> {
            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Rendering nothing because faces is invalid.
            // Should receive warning from validateFaces
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(bgColor, color, TOLERANCE);
        });
    }

    @Test(timeout=10000)
    public void testFaceLengthChange() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), 800, 800, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            buildBox();
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            Color color = getColor(testScene, WIDTH / 4, WIDTH / 4);
            assertColorEquals(Color.RED, color, TOLERANCE);

            // Valid change of faces
            triMesh.getFaces().setAll( 5, 2, 3, 1, 7, 3);

        });
        waitFirstFrame();
        runAndWait(() -> {
            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Rendering nothing because faceSmoothingGroups is invalid.
            // Should receive warning from validateFacesSmoothingGroups
            Color color = getColor(testScene, WIDTH / 4, WIDTH / 4);
            assertColorEquals(bgColor, color, TOLERANCE);
            // Reset faceSmoothingGroups
            triMesh.getFaceSmoothingGroups().setAll();
        });
        waitFirstFrame();
        runAndWait(() -> {
            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Rendering a triangle
            Color color = getColor(testScene, WIDTH / 4, WIDTH / 4);
            assertColorEquals(Color.RED, color, TOLERANCE);
            assertColorDoesNotEqual(bgColor, color, TOLERANCE);
        });
    }

    @Test(timeout=5000)
    public void testResetFaceSmoothingGroup() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), 800, 800, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            buildBox();
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(Color.RED, color, TOLERANCE);

            triMesh.getFaceSmoothingGroups().setAll();
        });
        waitFirstFrame();
        runAndWait(() -> {
            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Empty Sm should not affect rendering
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(Color.RED, color, TOLERANCE);
        });
    }

    @Test(timeout=5000)
    public void testUpdateMesh() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), 800, 800, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            buildBox();
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Rendering nothing. Should receive warning from validatePoints
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(Color.RED, color, TOLERANCE);

            color = getColor(testScene, WIDTH / 5, WIDTH / 5);
            assertColorEquals(bgColor, color, TOLERANCE);
            // set points
            triMesh.getPoints().setAll(1.5f, 1.5f, 1.5f,
                            1.5f, 1.5f, -1.5f,
                            1.5f, -1.5f, 1.5f,
                            1.5f, -1.5f, -1.5f,
                            -1.5f, 1.5f, 1.5f,
                            -1.5f, 1.5f, -1.5f,
                            -1.5f, -1.5f, 1.5f,
                            -1.5f, -1.5f, -1.5f);
            triMesh.getTexCoords().setAll(0, 0,
                            1, 0,
                            0, 1,
                            1, 1);
            triMesh.getFaces().setAll(5, 2, 3, 1, 7, 3);
            triMesh.getFaceSmoothingGroups().setAll(1);
        });
        waitFirstFrame();
        runAndWait(() -> {
            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            Color color = getColor(testScene, WIDTH / 5, WIDTH / 5);
            assertColorEquals(Color.RED, color, TOLERANCE);
        });
    }

    @Test(timeout = 5000)
    public void testDegeneratedMeshUpdateFaces() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), 800, 800, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            buildSquare();
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Rendering 2 Triangles that form a square
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(Color.RED, color, TOLERANCE);

            color = getColor(testScene, WIDTH / 2 + 10, WIDTH / 2 + 10);
            assertColorEquals(Color.RED, color, TOLERANCE);
            // set faces with degenerated triangle
            triMesh.getFaces().setAll(
                    2, 0, 1, 0, 3, 0,
                    2, 0, 1, 0, 1, 0);
        });
        waitFirstFrame();
        runAndWait(() -> {
            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }

            // Should render 1 Triangle
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(Color.RED, color, TOLERANCE);
            color = getColor(testScene, WIDTH / 2 + 10, WIDTH / 2 + 10);
            assertColorEquals(bgColor, color, TOLERANCE);

        });
    }

    @Test(timeout = 5000)
    public void testDegeneratedMeshUpdatePoints() {
        runAndWait(() -> {
            testStage = getStage();
            testStage.setTitle("TriangleMesh Validation Test");

            // Intentionally set depth buffer to false to reduce test complexity
            testScene = new Scene(buildScene(), 800, 800, true);
            testScene.setFill(bgColor);
            addCamera(testScene);
            buildSquare();
            testStage.setScene(testScene);
            testStage.show();
        });
        waitFirstFrame();
        runAndWait(() -> {

            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }
            // Rendering 2 Triangles that form a square
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(Color.RED, color, TOLERANCE);

            color = getColor(testScene, WIDTH / 2 + 10, WIDTH / 2 + 10);
            assertColorEquals(Color.RED, color, TOLERANCE);
            // set points that casuses a degenerated triangle
            triMesh.getPoints().setAll(
                    1.5f, -1.5f, 0f,
                    1.5f, -1.5f, 0f,
                    -1.5f, 1.5f, 0f,
                    -1.5f, -1.5f, 0f);
        });
        waitFirstFrame();
        runAndWait(() -> {
            if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
                System.out.println("*************************************************************");
                System.out.println("*      Platform isn't SCENE3D capable, skipping 3D test.    *");
                System.out.println("*************************************************************");
                return;
            }

            // Should render 1 Triangle
            Color color = getColor(testScene, WIDTH / 3, WIDTH / 3);
            assertColorEquals(Color.RED, color, TOLERANCE);
            color = getColor(testScene, WIDTH / 2 + 10, WIDTH / 2 + 10);
            assertColorEquals(bgColor, color, TOLERANCE);

        });
    }

    void buildSquare() {

        float points[] = {
            1.5f, 1.5f, 0f,
            1.5f, -1.5f, 0f,
            -1.5f, 1.5f, 0f,
            -1.5f, -1.5f, 0f
        };

        float texCoords[] = {0, 0
        };

        int faceSmoothingGroups[] = {
            1, 1
        };

        int faces[] = {
            2, 0, 1, 0, 3, 0,
            2, 0, 0, 0, 1, 0
        };

        triMesh.getPoints().setAll(points);
        triMesh.getTexCoords().setAll(texCoords);
        triMesh.getFaces().setAll(faces);
        triMesh.getFaceSmoothingGroups().setAll(faceSmoothingGroups);
    }

    void buildBox() {

        float points[] = {
            1, 1, 1,
            1, 1, -1,
            1, -1, 1,
            1, -1, -1,
            -1, 1, 1,
            -1, 1, -1,
            -1, -1, 1,
            -1, -1, -1,};

        float texCoords[] = {0, 0,
            0, 1,
            1, 0,
            1, 1};

        int faceSmoothingGroups[] = {
            1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4
        };

        int faces[] = {
            0, 0, 2, 2, 1, 1,
            2, 2, 3, 3, 1, 1,
            4, 0, 5, 1, 6, 2,
            6, 2, 5, 1, 7, 3,
            0, 0, 1, 1, 4, 2,
            4, 2, 1, 1, 5, 3,
            2, 0, 6, 2, 3, 1,
            3, 1, 6, 2, 7, 3,
            0, 0, 4, 1, 2, 2,
            2, 2, 4, 1, 6, 3,
            1, 0, 3, 1, 5, 2,
            5, 2, 3, 1, 7, 3,};

        triMesh.getPoints().setAll(points);
        triMesh.getTexCoords().setAll(texCoords);
        triMesh.getFaces().setAll(faces);
        triMesh.getFaceSmoothingGroups().setAll(faceSmoothingGroups);
    }

    private Group buildScene() {
        triMesh = new TriangleMesh();
        material = new PhongMaterial();
        material.setDiffuseColor(Color.RED);
        material.setSpecularColor(Color.rgb(30, 30, 30));
        meshView = new MeshView(triMesh);
        meshView.setMaterial(material);
        meshView.setScaleX(200);
        meshView.setScaleY(200);
        meshView.setScaleZ(200);
        meshView.setTranslateX(400);
        meshView.setTranslateY(400);
        meshView.setTranslateZ(10);

        root = new Group(meshView, new AmbientLight());
        return root;
    }

    private PerspectiveCamera addCamera(Scene scene) {
        PerspectiveCamera perspectiveCamera = new PerspectiveCamera(false);
        scene.setCamera(perspectiveCamera);
        return perspectiveCamera;
    }
}
